﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.IO;
using System.Xml;

namespace NRapid.Config
{
    /// <summary>
    /// NRapid项目配置管理类
    /// </summary>
    public class ConfigurationManager
    {
        public static NRapid.Config.ConnectionStringSettingsCollection ConnectionStrings = null;
        public static Dictionary<string, NRapid.Config.RedisData> RedisConfigs = null;
        public static bool? debug=null;
        public static Dictionary<string,NRapid.Config.Config> JsonDataList = null;
        public static Dictionary<string, Oauth2Data> oauth2DataList = null;
        public static AlipayPcData alipayPc = null;
        public static TenpayPcData tenpayPc = null;
        /// <summary>
        /// 获取配置
        /// </summary>
        /// <param name="appName">模块名</param>
        /// <param name="root">项目根目录</param>
        /// <returns></returns>
        public static Config GetConfig(string appName,string root)
        {
            string configFileName =System.IO.Path.Combine (root,"config.json");
            return GetConfig(appName, configFileName,root);
        }

        /// <summary>
        /// 获取全局配置
        /// </summary>
        /// <param name="appRoot">项目根目录</param>
        public static void Load(string appRoot)
        {
            if (ConfigurationManager.JsonDataList == null)
            {
                //debug
                //if (ConfigurationManager.debug == null)
                //{
                //    string webConfig = Path.Combine(appRoot, "Web.config");
                //    XmlDocument doc = new XmlDocument();
                //    if (File.Exists(webConfig))
                //    {
                //        doc.Load(webConfig);
                //        XmlNode compilationNode = doc.DocumentElement.SelectSingleNode("configuration/system.web/compilation[@debug]");
                //        if (compilationNode != null)
                //        {
                //            ConfigurationManager.debug = compilationNode.Attributes["debug"].Value == "true";
                //        }
                //        else
                //        {
                //            ConfigurationManager.debug = true;
                //        }
                //    }
                //    else
                //    {
                //        ConfigurationManager.debug = true;
                //    }
                //}
                //连接字符串
                if (ConfigurationManager.ConnectionStrings == null)
                {
                    string[] dirs = Directory.GetDirectories(appRoot);
                    ConfigurationManager.ConnectionStrings = new NRapid.Config.ConnectionStringSettingsCollection();
                    ConfigurationManager.JsonDataList = new Dictionary<string, Config>();
                    NRapid.Config.ConnectionStringSettings setting = null;
                    if (ConfigurationManager.RedisConfigs != null)
                    {
                        ConfigurationManager.RedisConfigs.Clear();
                    }
                    else
                    {
                        ConfigurationManager.RedisConfigs = new Dictionary<string, RedisData>();
                    }
                    if (dirs.Length > 0)
                    {
                        for (int i = 0; i < dirs.Length; i++)
                        {
                            string app = Path.GetFileName(dirs[i]);
                            string configFileName = Path.Combine(dirs[i], "config.json");
                            if (File.Exists(configFileName))
                            {
                                Config config = GetConfig(app, configFileName, appRoot);
                                ConfigurationManager.JsonDataList.Add(app, config);
                                for (int j = 0; j < config.connectionStrings.Count; j++)
                                {
                                    ConnectionString conStr = config.connectionStrings[j];

                                    if (!ConfigurationManager.ConnectionStrings.ContainsKey(conStr.name))
                                    {
                                        setting = new ConnectionStringSettings();
                                        setting.Name = conStr.name;
                                        setting.ConnectionString = conStr.value;
                                        setting.ProviderName = conStr.provider;
                                        ConfigurationManager.ConnectionStrings.Add(setting);
                                    }
                                }
                                RedisData redisData = new RedisData();
                                redisData.redisConfigAutoStart = config.redisConfigAutoStart;
                                redisData.redisConfigMaxReadPoolSize = config.redisConfigMaxReadPoolSize;
                                redisData.redisConfigMaxWritePoolSize = config.redisConfigMaxWritePoolSize;
                                redisData.redisReadOnlyHosts = config.redisReadOnlyHosts;
                                redisData.redisReadWriteHosts = config.redisReadWriteHosts;
                                ConfigurationManager.RedisConfigs.Add(app, redisData);
                            }
                        }
                    }
                }
            }   
        }
        static public bool JsonDataContainsKey(LitJson.JsonData data, string key)
        {
            bool result = false;
            if (data == null)
                return result;
            if (!data.IsObject)
            {
                return result;
            }
            IDictionary tdictionary = data as IDictionary;
            if (tdictionary == null)
                return result;
            if (tdictionary.Contains(key))
            {
                result = true;
            }
            return result;
        }
        /// <summary>
        /// 获取模块配置并初始化
        /// </summary>
        /// <param name="appName">模块名</param>
        /// <param name="configFileName">配置文件路径</param>
        /// <param name="root">项目根目录</param>
        /// <returns></returns>
        public static Config GetConfig(string appName, string configFileName,string root)
        {
            Config config = new Config();
            if (File.Exists(configFileName))
            {
                StreamReader sr = null;// new StreamReader(configFileName,System.Text.Encoding.UTF8);
                sr = File.OpenText(configFileName);
                string json = sr.ReadToEnd();
                sr.Dispose();
                config.JsonData = LitJson.JsonMapper.ToObject(json);
                config.defaultStyle = config.JsonData["defaultStyle"].ToString();
                int.TryParse(config.JsonData["urlMode"].ToString(), out config.UrlMode);
                config.connectionStrings = new System.Collections.Generic.List<ConnectionString>();
                
                bool.TryParse(config.JsonData["compressHTML"].ToString(), out config.CompressHTML);
                config.cookiePrefix = config.JsonData["cookiePrefix"].ToString();
                config.sessionPrefix = config.JsonData["sessionPrefix"].ToString();
                config.urlPrefix = config.JsonData["urlPrefix"].ToString();
                config.urlExtension = config.JsonData["urlExtension"].ToString();
                config.version = config.JsonData["version"].ToString();
                bool.TryParse(config.JsonData["autoVersion"].ToString(), out config.autoVersion);
                ConnectionString conStr = null;
                if (JsonDataContainsKey(config.JsonData, "connectionStrings"))
                {
                    LitJson.JsonData connectionStringArray = config.JsonData["connectionStrings"];
                    for (int i = 0; i < connectionStringArray.Count; i++)
                    {
                        conStr = new ConnectionString();
                        conStr.name = connectionStringArray[i]["name"].ToString();
                        conStr.provider = connectionStringArray[i]["providerName"].ToString();
                        conStr.value = connectionStringArray[i]["connectionString"].ToString();
                        //修正conStr.value|ModuleDataDirectory|,|DataDirectory|
                        if (conStr.value.IndexOf("|ModuleDataDirectory|") > -1)
                        {
                            conStr.value = conStr.value.Replace("|ModuleDataDirectory|", root + appName + "\\Data\\");
                        }
                        if (conStr.value.IndexOf("|DataDirectory|") > -1)
                        {
                            conStr.value = conStr.value.Replace("|DataDirectory|", root + "App_Data\\");
                        }
                        config.connectionStrings.Add(conStr);
                    }
                }
                if (JsonDataContainsKey(config.JsonData, "rewriteDirectory"))
                {
                    LitJson.JsonData rewriteDirectory = config.JsonData["rewriteDirectory"];
                    RewriteDirectory rd;
                    for (int i = 0; i < rewriteDirectory.Count; i++)
                    {
                        config.rewriteDirectoryList.Clear();
                        rd = new RewriteDirectory();
                        rd.from = rewriteDirectory[i]["from"].ToString();
                        rd.to = rewriteDirectory[i]["to"].ToString();
                        config.rewriteDirectoryList.Add(rd);
                    }
                }
                if (JsonDataContainsKey(config.JsonData, "rewriteFile"))
                {
                    LitJson.JsonData rewriteFile = config.JsonData["rewriteFile"];
                    RewriteFile rf;
                    for (int i = 0; i < rewriteFile.Count; i++)
                    {
                        config.rewriteFileList.Clear();
                        rf = new RewriteFile();
                        rf.from = rewriteFile[i]["from"].ToString();
                        rf.to = rewriteFile[i]["to"].ToString();
                        config.rewriteFileList.Add(rf);
                    }
                }
                if (JsonDataContainsKey(config.JsonData, "payments"))
                {
                    if (JsonDataContainsKey(config.JsonData["payments"], "alipaypc"))
                    {
                        alipayPc = new AlipayPcData();
                        LitJson.JsonData alipayPcJson = config.JsonData["payments"]["alipaypc"];
                        alipayPc.partner = alipayPcJson["partner"].ToString();
                        alipayPc.key = alipayPcJson["key"].ToString();
                        alipayPc.email = alipayPcJson["email"].ToString();
                        alipayPc.type = alipayPcJson["type"].ToString();
                        alipayPc.return_url = alipayPcJson["return_url"].ToString();
                        alipayPc.notify_url = alipayPcJson["notify_url"].ToString();
                    }
                    if (JsonDataContainsKey(config.JsonData["payments"],"tenpaypc"))
                    {
                        tenpayPc = new TenpayPcData();
                        LitJson.JsonData tenpayPcJson = config.JsonData["payments"]["tenpaypc"];
                        tenpayPc.partner = tenpayPcJson["partner"].ToString();
                        tenpayPc.key = tenpayPcJson["key"].ToString();
                        tenpayPc.type = tenpayPcJson["type"].ToString();
                        tenpayPc.return_url = tenpayPcJson["return_url"].ToString();
                        tenpayPc.notify_url = tenpayPcJson["notify_url"].ToString();
                    }
                }
                if (JsonDataContainsKey(config.JsonData, "oauth2"))
                {
                    LitJson.JsonData Oauth2 = config.JsonData["oauth2"];
                    Oauth2Data oauth2Data = null;
                    if (ConfigurationManager.oauth2DataList == null)
                    {
                        ConfigurationManager.oauth2DataList = new Dictionary<string, Oauth2Data>();
                    }
                    for (int i = 0; i < Oauth2.Count; i++)
                    {
                        oauth2Data = new Oauth2Data();
                        oauth2Data.name = Oauth2[i]["name"].ToString();
                        oauth2Data.id = Oauth2[i]["id"].ToString();
                        oauth2Data.key = Oauth2[i]["key"].ToString();
                        oauth2Data.return_url = Oauth2[i]["return_url"].ToString();
                        if (!ConfigurationManager.oauth2DataList.ContainsKey(oauth2Data.name))
                        {
                            ConfigurationManager.oauth2DataList.Add(oauth2Data.name, oauth2Data);
                        }
                    }
                }
                if (JsonDataContainsKey(config.JsonData, "redis"))
                {
                    LitJson.JsonData redisConfig = config.JsonData["redis"];
                    bool.TryParse(redisConfig["autoStart"].ToString(), out config.redisConfigAutoStart);
                    int.TryParse(redisConfig["maxReadPoolSize"].ToString(), out config.redisConfigMaxReadPoolSize);
                    int.TryParse(redisConfig["maxWritePoolSize"].ToString(), out config.redisConfigMaxWritePoolSize);

                    LitJson.JsonData readWriteHosts = redisConfig["readWriteHosts"];
                    if (readWriteHosts == null || readWriteHosts.Count < 1)
                    {
                        config.redisReadWriteHosts = null;
                    }
                    else
                    {
                        config.redisReadWriteHosts = new string[readWriteHosts.Count];
                    }
                    for (int i = 0; i < readWriteHosts.Count; i++)
                    {
                        config.redisReadWriteHosts[i] = readWriteHosts[i].ToString();
                    }
                    LitJson.JsonData readOnlyHosts = redisConfig["readOnlyHosts"];
                    if (readOnlyHosts == null || readOnlyHosts.Count < 1)
                    {
                        config.redisReadOnlyHosts = null;
                    }
                    else
                    {
                        config.redisReadOnlyHosts = new string[readWriteHosts.Count];
                    }
                    for (int i = 0; i < readOnlyHosts.Count; i++)
                    {
                        config.redisReadOnlyHosts[i] = readOnlyHosts[i].ToString();
                    }
                }
            }
            
            return config;
        }
    }
}
